//
//  DataOperationManager.m
//  etionCBLogic
//
//  Created by wjxfhxy on 13-3-12.
//
//

#import "XMSDataOperationManager.h"

@interface XMSDataOperationManager ()
{
    NSInteger _requestState;
    
    NSInteger _requestCount;

    NSOperationQueue *_singleQueue;

    NSOperationQueue *_queuePool;
    
    XMSDispatchQueueWrapper *_requeststatqueue;
    
    XMSDispatchQueueWrapper *_thirdDispatchQueueWrapper;
}

@end

@implementation XMSDataOperationManager

@synthesize delegate = _delegate;

@synthesize name = _name;

@synthesize dispatchQueueWrapper = _thirdDispatchQueueWrapper;

- (id)init
{
    if (self = [super init])
    {
        _delegate = nil;
        _requestState = EDOMRequestStateTypeCanRequest;
        
        _requeststatqueue = [[XMSDispatchQueueWrapper alloc]initWithName:""];
        
        _requestCount = 0;
        self.name = NSStringFromClass([self class]);
    }

    return self;
}

- (id)initWithDataOperationManagerDelegate:(id <XMSDataOperationManagerDelegate>)domdelegate
{
    self = [self init];

    _delegate = domdelegate;

    return self;
}

- (id)initWithDataOperationManagerDelegate:(id <XMSDataOperationManagerDelegate>)domdelegate AttachDOM:(XMSDataOperationManager *)attachdom
{
    id this = [self initWithDataOperationManagerDelegate:domdelegate];
    BOOL bResult = [attachdom attachDataOperationManager:[NSArray arrayWithObject:self]];
    if (bResult == NO)
    {
        [this autorelease_mm];
        this = nil;
    }
    return this;
}

- (id)initWithDispatchQueueWrapper:(XMSDispatchQueueWrapper*)wrapper
{
    self = [self init];
    
    _thirdDispatchQueueWrapper = [wrapper retain_mm];
    
    return self;
}

- (void)dealloc
{
    [_name release_mm];
    _delegate = nil;
    [self _detachDataOperationManager];
    [_requeststatqueue release_mm];
    [_singleQueue release_mm];
    [_queuePool release_mm];
    [_thirdDispatchQueueWrapper release_mm];
    superdealloc_mm;
}

- (BOOL)dataOperationManagerDelegate:(id <XMSDataOperationManagerDelegate>)domdelegate attachDOMCls:(NSArray *)arAttachdom operation:(void (^)(NSArray *arDom))operation
{
    __block BOOL nResult = FALSE;
    NSMutableArray *ar = [[NSMutableArray new] autorelease_mm];
    [arAttachdom enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
    {
        nResult = YES;
        id i = [[[(Class) obj alloc] initWithDataOperationManagerDelegate:domdelegate AttachDOM:self] autorelease_mm];
        if (i == nil)
        {
            *stop = YES;
            nResult = NO;
        }
        else
        {
            [ar addObject:i];
        }
    }];
    if (nResult == YES)
        operation(ar);
    [self detachDataOperationManager:ar];
    return nResult;
}

- (BOOL)isRejectRequest
{
    BOOL(^fun)() = ^BOOL()
    {
        if ((_requestState & EDOMRequestStateTypeReject) == EDOMRequestStateTypeReject)
            return YES;
        return NO;
    };

    __block BOOL bResult = NO;

    [_requeststatqueue dispatchThreadSync:^
    {
        bResult = fun();
    }];

    return bResult;
}

- (BOOL)isStopRequest
{
    BOOL(^fun)() = ^BOOL()
    {
        if ((_requestState & EDOMRequestStateTypeStop) == EDOMRequestStateTypeStop)
            return YES;
        return NO;
    };

    __block BOOL bResult = NO;

    [_requeststatqueue dispatchThreadSync:^
    {
        bResult = fun();
    }];

    return bResult;
}

- (BOOL)isRequesting
{
    BOOL(^fun)() = ^BOOL()
    {
        if ((_requestState & EDOMRequestStateTypeRequesting) == EDOMRequestStateTypeRequesting)
            return YES;
        return NO;
    };

    __block BOOL bResult = NO;

    [_requeststatqueue dispatchThreadSync:^
    {
        bResult = fun();
    }];

    return bResult;
}

- (BOOL)isCanRequest
{
    BOOL(^fun)() = ^BOOL()
    {
        if ((_requestState & EDOMRequestStateTypeReject) == EDOMRequestStateTypeReject)
            return YES;
        if ((_requestState & EDOMRequestStateTypeStop) == EDOMRequestStateTypeStop)
            return YES;
        return NO;
    };

    __block BOOL bResult = NO;

    [_requeststatqueue dispatchThreadSync:^
    {
        bResult = fun();
    }];

    return !bResult;
}

- (BOOL)attachDataOperationManager:(NSArray *)arDom
{
    BOOL(^fun)() = ^BOOL
    {
        if (self.isRejectRequest == YES)
            return NO;
        if (self.isStopRequest == YES)
            return NO;

        if (nil == _arAttachdom)
            _arAttachdom = [NSMutableArray new];
        [_arAttachdom addObjectsFromArray:arDom];

        return YES;
    };
    __block BOOL bReslut = NO;
    [_requeststatqueue dispatchThreadSync:^
    {
        bReslut = fun();
    }];

    return bReslut;
}

- (void)detachAllDataOperationManager
{
    [_requeststatqueue dispatchThreadSync:^
    {
        [_arAttachdom removeAllObjects];
        [_arAttachdom release_mm];
        _arAttachdom = nil;

    }];
}

- (BOOL)_detachDataOperationManager
{
    [_arAttachdom removeAllObjects];
    [_arAttachdom release_mm];
    _arAttachdom = nil;
    return YES;
}

- (void)detachDataOperationManager:(NSArray *)arDom;
{
    if (arDom.count > 0)
    {
        [_requeststatqueue dispatchThreadSync:^
        {
            [_arAttachdom removeObjectsInArray:arDom];
        }];
    }
}

- (void)terminateRequestAsyncCompletion:(void (^)(NSInteger nResult))completion
{
    XMSDataOperationManager *dom = self;
    id <XMSDataOperationManagerDelegate> domdelegate = _delegate;
    DispatchThread(^
    {
        (void)domdelegate;
     //   if ([domdelegate respondsToSelector:@selector(WillTerminateRequest:)] == YES)
     //       [domdelegate WillTerminateRequest:self];
        completion([dom terminateRequest]);
     //   if ([domdelegate respondsToSelector:@selector(DidTerminateRequest:)] == YES)
     //       [domdelegate DidTerminateRequest:self];
    });
}

- (void)terminateRequestAsyncCompletion
{
    [self terminateRequestAsyncCompletion:^(NSInteger nResult)
    {
    }];
}

- (BOOL)terminateRequest:(BOOL)bRejectrequest
{
    if(self.isRejectRequest == YES)
        return YES;
    
    BOOL(^fun)() = ^BOOL
    {
        if ((_requestState & EDOMRequestStateTypeRequesting) == EDOMRequestStateTypeRequesting)
        {
            if ((_requestState & EDOMRequestStateTypeCanRequest) == EDOMRequestStateTypeCanRequest)
                _requestState = (_requestState & (~EDOMRequestStateTypeCanRequest));
            _requestState = (_requestState | EDOMRequestStateTypeStop);
        }
        if (bRejectrequest == YES)
            _requestState = (_requestState | EDOMRequestStateTypeReject);

        BOOL bResult = NO;

        bResult = [self terminateSelfRequest:bRejectrequest];
        if (bResult == YES)
        {
//            for(void(^block)(BOOL b) in _terminateblock)
//            {
//                block(bRejectrequest);
//            }
            if (_arAttachdom.count > 0)
            {
                bResult = NO;
                NSInteger nCount = 0;
                NSMutableArray *arAttachms = [[NSMutableArray new] autorelease_mm];
                [arAttachms addObjectsFromArray:_arAttachdom];
                for (XMSDataOperationManager *dom in arAttachms)
                {
                    BOOL b = [dom terminateRequest:bRejectrequest];
                    if (b == YES)
                    {
                        nCount++;
                        if (bRejectrequest == YES)
                        {
                            [_arAttachdom removeObject:dom];
                        }
                    }
                }
                if (nCount == arAttachms.count)
                    bResult = YES;
            }
        }

        if (bResult == YES)
        {
            [_singleQueue cancelAllOperations];

            [_queuePool cancelAllOperations];
        }

        return bResult;
    };
    __block BOOL bResutl = NO;
    [_requeststatqueue dispatchThreadSync:^
    {
        bResutl = fun();
    }];

    if (bResutl == YES&& bRejectrequest == NO)
    {
        while (self.isCanRequest != YES)
        {
        }
    }

    return bResutl;
}

- (BOOL)terminateRequest
{
    return [self terminateRequest:YES];
}

- (BOOL)cancelTerminateRequest
{
    [_requeststatqueue dispatchThreadSync:^
    {
        if ((_requestState & EDOMRequestStateTypeReject) == EDOMRequestStateTypeReject)
            _requestState = (_requestState & (~EDOMRequestStateTypeReject));
        if ((_requestState & EDOMRequestStateTypeStop) == EDOMRequestStateTypeStop)
            _requestState = (_requestState & (~EDOMRequestStateTypeStop));
    }];
    
    return YES;
}

- (BOOL)terminateSelfRequest:(BOOL)bRejectrequest
{
    return YES;
}

- (void)stopRequestAsyncCompletion:(void (^)(NSInteger nResult))completion
{
    XMSDataOperationManager *dom = self;
    id <XMSDataOperationManagerDelegate> domdelegate = _delegate;
    DispatchThread(^
    {
        (void)domdelegate;
    //    if ([domdelegate respondsToSelector:@selector(WillTerminateRequest:)] == YES)
    //        [domdelegate WillTerminateRequest:self];
        completion([dom stopRequest]);
     //   if ([domdelegate respondsToSelector:@selector(DidTerminateRequest:)] == YES)
     //       [domdelegate DidTerminateRequest:self];
    });
}

- (void)stopRequestAsyncCompletion
{
    [self stopRequestAsyncCompletion:^(NSInteger nResult)
    {

    }];
}

- (BOOL)stopRequest
{
    return [self terminateRequest:NO];
}

//- (void)addTerminateBlock:(void(^)(BOOL bRejectrequest))block
//{
//    if(_terminateblock==nil)
//        _terminateblock=[NSMutableArray new];
//    [_terminateblock addObject:block];
//}

- (void)request:(void (^)())block
{
    EDOMRequestStateType(^fun1)() = ^EDOMRequestStateType
    {
        if (self.isRejectRequest == YES)
            return EDOMRequestStateTypeReject;
        if (self.isStopRequest == YES)
            return EDOMRequestStateTypeStop;
        if (_requestCount == 0)
            _requestState = (_requestState | EDOMRequestStateTypeRequesting);
        _requestCount++;
        return EDOMRequestStateTypeRequesting;
    };
    void(^fun2)() = ^
    {
        if (self.isRejectRequest == YES)
            return;
        _requestCount--;
        if (_requestCount == 0)
        {
            if ((_requestState & EDOMRequestStateTypeRequesting) == EDOMRequestStateTypeRequesting)
                _requestState = (_requestState & (~EDOMRequestStateTypeRequesting));
            if ((_requestState & EDOMRequestStateTypeStop) == EDOMRequestStateTypeStop)
                _requestState = (_requestState & (~EDOMRequestStateTypeStop));
            _requestState = (_requestState | EDOMRequestStateTypeCanRequest);
        }

    };

    __block EDOMRequestStateType type = EDOMRequestStateTypeCanRequest;
    [_requeststatqueue dispatchThreadSync: ^
    {
        type = fun1();
    }];
    if (type == EDOMRequestStateTypeRequesting)
    {
        @autoreleasepool
        {
            block();
        }
    }
    [_requeststatqueue dispatchThreadSync:^
    {
        fun2();
    }];
}

- (EDOMRequestStateType)request:(BOOL)bAsync newThread:(BOOL)bNewthread block:(void (^)())block
{
    if (self.isCanRequest != YES)
        return EDOMRequestStateTypeCanNotRequest;
    else
    {
        if(bNewthread==NO)
        {
            if (bAsync == YES)
            {
                id <XMSDataOperationManagerDelegate> delegate = _delegate;
                DispatchThread(^
                {
                    @autoreleasepool
                    {
                        (void)delegate;
                        [self request:block];
                    }
                });
            }
            else
                [self request:block];
        }
        else if (bNewthread==YES)
        {
            id <XMSDataOperationManagerDelegate> delegate = _delegate;
            DispatchGlobalThreadAsync(^
            {
                @autoreleasepool
                {
                    (void)delegate;
                    [self request:block];
                }
            });
        }
    }
    return EDOMRequestStateTypeCanRequest;
}

- (EDOMRequestStateType)requestAsyncBlock:(void (^)())block
{
    return [self request:YES newThread:NO block:block];
}

- (EDOMRequestStateType)requestSyncBlock:(void (^)())block
{
    return [self request:NO newThread:NO block:block];
}

- (EDOMRequestStateType)requestThreadBlock:(void (^)())block
{
    return [self request:YES newThread:YES block:block];
}

- (BOOL)isDOMAttachRequesting
{
    BOOL (^fun)() = ^BOOL()
    {
        __block BOOL bResult = NO;
        if (self.isRequesting == YES)
            bResult = YES;
        else
        {
            [_arAttachdom enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
            {
                XMSDataOperationManager *dom = (XMSDataOperationManager *) obj;
                bResult = [dom isDOMAttachRequesting];
                if (bResult == YES)
                {
                    *stop = YES;
                }
            }];
        }
        return bResult;
    };


    __block BOOL bResult = NO;
    [_requeststatqueue dispatchThreadSync: ^
    {
        bResult = fun();
    }];
    return bResult;
}

- (void)dispatchQueueRunType:(EDispatchQueueRunType)type checkTerminate:(BOOL)check asyncBlock:(void (^)())block
{
//    if (self.isCanRequest != YES)
//        return EDOMRequestStateTypeCanNotRequest;
//    else
//    {
        switch(type)
        {
            case EDispatchQueueRunTypeAsync:
            {
                [_thirdDispatchQueueWrapper dispatchThreadAsync:^
                {
                    if(check==YES)
                        [self request:block];
                    else
                        block();
                }];
                break;
            }
            case EDispatchQueueRunTypeSync:
            {
                [_thirdDispatchQueueWrapper dispatchThreadSync:^
                {
                    if(check==YES)
                        [self request:block];
                    else
                        block();
                }];
                break;
            }
        }
//    }
}

@end

@implementation XMSDataOperationManager (SingleQueue)

- (EDOMRequestStateType)requestQueueAsyncBlock:(void (^)())block
{
    if (self.isCanRequest != YES)
        return EDOMRequestStateTypeCanNotRequest;
    else
    {
        if (_singleQueue == nil)
        {
            [_requeststatqueue dispatchThreadSync: ^
            {
                if (_singleQueue == nil)
                {
                    _singleQueue = [NSOperationQueue new];
                    [_singleQueue setMaxConcurrentOperationCount:1];
                }
            }];
        }
        [_singleQueue addOperationWithBlock:^
        {
            [self request:block];
        }];
    }
    return EDOMRequestStateTypeCanRequest;
}

- (EDOMRequestStateType)requestQueueSyncBlock:(void (^)())block
{
    if (self.isCanRequest != YES)
        return EDOMRequestStateTypeCanNotRequest;
    else
    {
        if (_singleQueue == nil)
        {
            [_requeststatqueue dispatchThreadSync: ^
            {
                if (_singleQueue == nil)
                {
                    _singleQueue = [NSOperationQueue new];
                    [_singleQueue setMaxConcurrentOperationCount:1];
                }
            }];
        }
        
        void(^fun)()=^
        {
            [self request:block];
        };

        [_singleQueue addOperationWithBlock:fun];
        [_singleQueue waitUntilAllOperationsAreFinished];
    }
    return EDOMRequestStateTypeCanRequest;
}

@end

@implementation XMSDataOperationManager (QueuePool)

-(BOOL)isIsQueuePoolWaitingFinish
{
    BOOL(^fun)()=^BOOL
    {
        if ((_requestState & EDOMRequestStateTypeWaitingQueueTasks) == EDOMRequestStateTypeWaitingQueueTasks)
            return YES;
        return NO;
    };
    
    __block BOOL bReslut=NO;
    [_requeststatqueue dispatchThreadSync: ^
    {
        bReslut = fun();
    }];
    return bReslut;
}

- (void)setQueuePoolMaxRun:(NSUInteger)nMax
{
    if (_queuePool == nil)
    {
        [_requeststatqueue dispatchThreadSync: ^
        {
            if (_queuePool == nil)
            {
                _queuePool = [NSOperationQueue new];
            }
            [_queuePool setMaxConcurrentOperationCount:nMax];
        }];
    }
}

- (EDOMRequestStateType)requestQueuePoolAsyncBlock:(void (^)())block
{
    if (self.isCanRequest != YES)
        return EDOMRequestStateTypeCanNotRequest;
    else
    {
        if (_queuePool == nil)
        {
            [_requeststatqueue dispatchThreadSync: ^
            {
                if (_queuePool == nil)
                {
                    _queuePool = [NSOperationQueue new];
                    [_queuePool setMaxConcurrentOperationCount:1];
                }
            }];
        }
        [_queuePool addOperationWithBlock:^
        {
            [self request:block];
        }];

    }
    return EDOMRequestStateTypeCanRequest;
}

- (EDOMRequestStateType)requestInvocationQueuePoolAsyncInvocation:(NSInvocationOperation *)invocation
{
    if (self.isCanRequest != YES)
        return EDOMRequestStateTypeCanNotRequest;
    else
    {
        if (_queuePool == nil)
        {
            [_requeststatqueue dispatchThreadSync: ^
            {
                if (_queuePool == nil)
                {
                    _queuePool = [NSOperationQueue new];
                    [_queuePool setMaxConcurrentOperationCount:2];
                }
            }];
        }
        [_queuePool addOperation:invocation];

    }
    return EDOMRequestStateTypeCanRequest;
}

- (NSArray *)queuePoolTask
{
    return [_queuePool operations];
}

- (NSUInteger)queuePoolTaskCount
{
    return [_queuePool operationCount];
}

- (void)waitUntilAllQueuePoolTasksAreFinished
{
    [_requeststatqueue dispatchThreadSync: ^
    {
        _requestState = (_requestState | EDOMRequestStateTypeWaitingQueueTasks);
    }];
    [_queuePool waitUntilAllOperationsAreFinished];
    [_requeststatqueue dispatchThreadSync: ^
    {
        _requestState = (_requestState & (~EDOMRequestStateTypeWaitingQueueTasks));
    }];
}

@end
